-- Procesor - plik glowny
-- Wejscia sterujace:
-- CLOCK<
-- RST# (reset)

library IEEE;
use IEEE.Std_Logic_1164.all;

entity processor1 is
  port (CLK, RST   : in std_logic);
end entity processor1;

architecture processor1_struct of processor1 is
  signal DATA_BUS, RAM_IN, RAM_OUT, ROM_OUT, RI_OUT, RN_OUT, REGX_OUT, REGY_OUT, GA_PC : std_logic_vector(7 downto 0);
  signal DATA_BUS3, FLAGS_IN : std_logic_vector(3 downto 0);
  signal ADDRESS_BUS, RAM_ADDR, ROM_ADDR, PC_OUT, CU_ARG1, CU_ARG2 : std_logic_vector(3 downto 0);
  signal GA : std_logic_vector(2 downto 0);
  signal ALU_INSTR, CU_INSTR, CU_ADRARG1, CU_ADRARG2, ERROR : std_logic_vector(1 downto 0);
  signal RAM_W, RAM_R, RAM_LAE, RAM_IE1, RAM_OE1, RAM_IE2, RAM_OE2 : std_logic;
  signal ROM_R, ROM_LAE, ROM_IE, ROM_OE : std_logic;
  signal PC_RESET, PC_INCR, RI_LAE, RN_LAE : std_logic;
  signal REGX_IE, REGX_OE, REGY_IE, REGY_OE, FLAGS_IE, FLAGS_OE, ALU_OE, ALU_START : std_logic;
  signal CU_CLOCK, CU_RESET, DE_DECODE : std_logic;
begin
  CU_CLOCK <= CLK;
  CU_RESET <= RST;
  
  -- Pamiec danych
  RAM: entity work.RAM
    port map (
       ADDRESS => RAM_ADDR,
       IE      => RAM_W,
       OE      => RAM_R,
       DATAIN  => RAM_IN,
       DATAOUT => RAM_OUT
    );
      
  -- Rejestr adresowy pamieci danych
  RegRAMAddress: entity work.REG4_LATCH
    port map (
       LAE     => RAM_LAE,
       DATAIN  => ADDRESS_BUS,
       DATAOUT => RAM_ADDR
    );
      
  -- Bufor danych pamieci danych
  RegRAMBuffer: entity work.DOUBLEREG8
    port map (
       IE1      => RAM_IE1,
       OE1      => RAM_OE1,
       DATAIN1  => RAM_OUT,
       DATAOUT1 => RAM_IN,
       
       IE2      => RAM_IE2,
       OE2      => RAM_OE2,
       DATAIN2  => DATA_BUS,
       DATAOUT2 => DATA_BUS
    );
      
----------------------------------

  -- Pamiec programu
  ROM: entity work.ROM
    port map (
       ADDRESS => ROM_ADDR,
       OE      => ROM_R,
       DATA    => ROM_OUT
    );
  
  -- Rejestr adresowy pamieci programu  
  RegROMAddress: entity work.REG4_LATCH
    port map (
       LAE     => ROM_LAE,
       DATAIN  => ADDRESS_BUS,
       DATAOUT => ROM_ADDR
    );
      
  -- Bufor danych pamieci programu
  RegROMBuffer: entity work.REG8
    port map (
       IE      => ROM_IE,
       OE      => ROM_OE,
       DATAIN  => ROM_OUT,
       DATAOUT => DATA_BUS
    );
    
----------------------------------

  -- Rejestr X przy ALU
  RegX: entity work.REG8_LATCH
    port map (
       LAE     => REGX_IE,
       DATAIN  => DATA_BUS,
       DATAOUT => REGX_OUT
    );
    
  -- Rejestr Y przy ALU
  RegY: entity work.REG8_LATCH
    port map (
       LAE     => REGY_IE,
       DATAIN  => DATA_BUS,
       DATAOUT => REGY_OUT
    );

  -- ALU
  ALU: entity work.ALU1
    port map (
      X       => REGX_OUT,
      Y       => REGY_OUT,
      INSTR   => ALU_INSTR,
      ALUOUT  => DATA_BUS,
      OE      => ALU_OE, -- cu
      START   => ALU_START,
      FLAGOUT => FLAGS_IN,
      FLAGW   => FLAGS_IE
    );
    
  -- Rejestr flag
  Flags: entity work.FLAGS
    port map (
      IE       => FLAGS_IE,
      OE       => FLAGS_OE, -- cu
      FLAGSIN  => FLAGS_IN,
      FLAGSOUT => DATA_BUS3
    );
  DATA_BUS3 <= DATA_BUS(3 downto 0);

----------------------------------

  -- Jednostka centralna
  CU: entity work.CU1
    port map (
      CLOCK         => CU_CLOCK,
      RESET         => CU_RESET,
      INSTR         => CU_INSTR,
      ADRARG1       => CU_ADRARG1,
      ADRARG2       => CU_ADRARG2,
      ARG1          => CU_ARG1,
      ARG2          => CU_ARG2,
      CU_GA         => GA,
      CU_ROM_LAE    => ROM_LAE,
      CU_ROM_R      => ROM_R,
      CU_ROM_IE     => ROM_IE,
      CU_ROM_OE     => ROM_OE,
      CU_PC_INCR    => PC_INCR,
      CU_PC_RESET   => PC_RESET,
      CU_RI_LAE     => RI_LAE,
      CU_RN_LAE     => RN_LAE,
      CU_DE_DECODE  => DE_DECODE,
      CU_RAM_LAE    => RAM_LAE,
      CU_RAM_IE1    => RAM_IE1,
      CU_RAM_IE2    => RAM_IE2,
      CU_RAM_OE1    => RAM_OE1,
      CU_RAM_OE2    => RAM_OE2,
      CU_RAM_R      => RAM_R,
      CU_RAM_W      => RAM_W,
      CU_REGX_IE    => REGX_IE,
      CU_REGY_IE    => REGY_IE,
      CU_ALU_INSTR  => ALU_INSTR,
      CU_ALU_START  => ALU_START,
      CU_ERROR      => ERROR
    );
    
  -- Dekoder
  Decoder: entity work.DECODER1
    port map (
      DECODE      => DE_DECODE,   
      INSTRUCTION => RI_OUT,           
      INSTR       => CU_INSTR,
      ADRARG1     => CU_ADRARG1,
      ADRARG2     => CU_ADRARG2,
      ARG1        => CU_ARG1,
      ARG2        => CU_ARG2  
    );

  -- Rejestr instrukcji
  RegInstr: entity work.REG8_LATCH
    port map (
       LAE     => RI_LAE,
       DATAIN  => DATA_BUS,
       DATAOUT => RI_OUT
    );

----------------------------------

  -- Generator adresu
  GENADD: entity work.GA
    port map (
      INPUT0 => GA_PC,
      INPUT1 => RN_OUT,
      INPUT2 => "ZZZZZZZZ",
      INPUT3 => "ZZZZZZZZ",
      INPUT4 => "ZZZZZZZZ",
      INPUT5 => "ZZZZZZZZ",
      INPUT6 => "ZZZZZZZZ",
      INPUT7 => "ZZZZZZZZ",
      OUTPUT => ADDRESS_BUS,
      S => GA
    );
    GA_PC(3 downto 0) <= PC_OUT;
    
  -- Licznik programu
  ProgCounter: entity work.PROG_COUNTER
    port map (
       RESET  => PC_RESET,
       INCR   => PC_INCR,
       CLOCK  => CU_CLOCK,
       OUTPUT => PC_OUT
    );
    
  -- Rejestr natychmiastowy
  RegImm: entity work.REG8_LATCH
    port map (
       LAE     => RN_LAE,
       DATAIN  => DATA_BUS,
       DATAOUT => RN_OUT
    );

end;